home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr10 / ehp10.zip / TEXT_2.C < prev    next >
C/C++ Source or Header  |  1993-06-19  |  45KB  |  1,104 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  text_2.c                                        */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - textbeginn (an textbeginn)                    */
  7. /*              - textende (an textende)                        */
  8. /*              - lines_down (anzahl von zeilen runter)         */
  9. /*              - lines_up (anzahl von zeilen hoch)             */
  10. /*              - screen_up (eine fenstergroesse hoch)          */
  11. /*              - screen_down (eine fenstergroesse runter)      */
  12. /*              - half_up (halbe fenstergroesse hoch)           */
  13. /*              - half_down (halbe fenstergroesse runter)       */
  14. /*              - insert (zeichen an akt. position einfuegen)   */
  15. /*              - enter_char (Zeichen an aktuelle Pos. kop.)    */
  16. /*              - koppel_line (Neue Zeile in Text einkoppeln)   */
  17. /*              - new_line (zeile splitten)                     */
  18. /*              - del_line (Zeile loeschen)                     */
  19. /*              - gotox (gehe zu Zeile X)                       */
  20. /*              - indent_line (aktuelle Zeile einruecken)       */
  21. /*              - fastleft (in Zeile ein Zeichen nach links)    */
  22. /*              - fastright (in Zeile ein Zeichen nach rechts)  */
  23. /*              - fastll (Zeilenlaenge der aktuellen Zeile)     */
  24. /*              - fastzeichen (Hole Zeichen aus akt. Zeile)     */
  25. /*              - put_zeile (Zeile in Datei schreiben)          */
  26. /*              - schreib_file (Schreib File auf Platte)        */
  27. /*              - tab_in_buff (Tab in Puffer einfuegen)         */
  28. /*              - lies_file (Datei einlesen)                    */
  29. /*              - free_text (Text freigeben)                    */
  30. /*              - save_delline (aktuelle zeile sichern)         */
  31. /*              - rest_delline (gespeicherte Zeile einfuegen)   */
  32. /****************************************************************/
  33.  
  34. #include "defs.h"
  35.  
  36. extern char backupflag;
  37. extern marker_typ marker[];
  38.  
  39. /* *** globale Daten und Initialisierung *** */
  40. extern char linebuff [3*MAXLENGTH+1], /* Zeilenpuffer                  */
  41.         bufflag,         /* Flag, ob linebuff belegt ist           */
  42.         *sd_line,        /* Zwischenspeicher fuer geloeschte Zeile */
  43.         space;           /* Globales Leerzeichen                   */
  44. char        *fastzeichen();
  45.  
  46. /****************************************************************
  47. *
  48. * FUNKTION:     textbeginn()    (an textanfang)
  49. * ERGEBNIS:     TRUE,FALSE
  50. * BESCHREIBUNG: - die erste zeile wird zur aktuellen
  51. *****************************************************************/
  52.  
  53. int textbeginn()
  54. {
  55.   check_buff();  /* evtl. Pufferinhalt in Text uebernehmen */
  56.   if(akt_winp->maxline >= 0)    /* nur wenn Datei nicht leer */
  57.   { /* Da dummy vor der ersten Zeile, ist erste Zeile Nachfolger von dummy */
  58.     akt_winp->alinep = akt_winp->dummyp->next;
  59.     akt_winp->textline = 0;
  60.     return(TRUE);
  61.   }
  62.   return(FALSE);
  63. }
  64.  
  65.  
  66. /****************************************************************
  67. *
  68. * FUNKTION:     textende()      (an textende)
  69. * ERGEBNIS:     TRUE
  70. * BESCHREIBUNG: - die letzte zeile wird zur aktuellen
  71. *****************************************************************/
  72.  
  73. int textende()
  74. {
  75.   check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  76.   /* dummy steht hinter letzter, also ist letzte Vorgaenger von dummy */
  77.   akt_winp->alinep = akt_winp->dummyp->prev;
  78.   akt_winp->textline = akt_winp->maxline;
  79.   return(TRUE);
  80. }
  81.  
  82.  
  83. /****************************************************************
  84. *
  85. * FUNKTION:     lines_down()    (anzahl von zeilen runter)
  86. *
  87. * PARAMETER:    int anz: anzahl zu ueberspringender zeilen
  88. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  89. * BESCHREIBUNG: - es wird versucht, anz zeilen im text nach unten
  90. *               zu springen.
  91. *****************************************************************/
  92.  
  93. int lines_down(anz)
  94. register int anz;
  95. {
  96.   /* *** interne Daten und Initialisierung *** */
  97.   register int hilf = anz; /* Zwischenspeicher fuer Parameter */
  98.  
  99.   if (anz > 0 && akt_winp->maxline >=0)
  100.   {
  101.     check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  102.  
  103.     while(anz-- && (akt_winp->textline < akt_winp->maxline))
  104.     {
  105.       akt_winp->textline++;
  106.       akt_winp->alinep = akt_winp->alinep->next;
  107.     }
  108.     return(hilf-anz-1);
  109.   }
  110.   return (0);
  111. }
  112.  
  113.  
  114. /****************************************************************
  115. *
  116. * FUNKTION:     lines_up()      (anzahl von zeilen hoch)
  117. *
  118. * PARAMETER:    int anz: anzahl zu ueberspringender zeilen
  119. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  120. * BESCHREIBUNG: - es wird versucht, anz zeilen im text nach oben
  121. *               zu springen.
  122. *****************************************************************/
  123.  
  124. int lines_up(anz)
  125. register int anz;
  126. {
  127.   /* *** interne Daten und Initialisierung *** */
  128.   register int hilf = anz; /* Zwischenspeicher fuer Parameter */
  129.  
  130.   if (anz > 0 && akt_winp->maxline >= 0)
  131.   {
  132.     check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  133.  
  134.     while(anz-- && akt_winp->textline)
  135.     {
  136.       akt_winp->textline--;
  137.       akt_winp->alinep = akt_winp->alinep->prev;
  138.     }
  139.     return(hilf-anz-1);
  140.   }
  141.   return (0);
  142. }
  143.  
  144.  
  145. /****************************************************************
  146. *
  147. * FUNKTION:     screen_up()     (eine bildschirmseite hoch)
  148. *
  149. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  150. * BESCHREIBUNG: - es wird versucht, eine bildschirmseite im text
  151. *               nach oben zu springen.
  152. *****************************************************************/
  153.  
  154. int screen_up()
  155. {
  156.   return(lines_up(akt_winp->dy));
  157. }
  158.  
  159.  
  160. /****************************************************************
  161. *
  162. * FUNKTION:     screen_down()   (eine bildschirmseite runter)
  163. *
  164. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  165. * BESCHREIBUNG: - es wird versucht, eine bildschirmseite im text
  166. *               nach unten zu springen.
  167. *****************************************************************/
  168.  
  169. int screen_down()
  170. {
  171.   return(lines_down(akt_winp->dy));
  172. }
  173.  
  174. /****************************************************************
  175. *
  176. * FUNKTION:     half_up()       (eine halbe bildschirmseite hoch)
  177. *
  178. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  179. * BESCHREIBUNG: - es wird versucht, eine halbe bildschirmseite
  180. *               im text nach oben zu springen.
  181. *****************************************************************/
  182.  
  183. int half_up()
  184. {
  185.   return(lines_up(akt_winp->dy / 2));
  186. }
  187.  
  188.  
  189. /****************************************************************
  190. *
  191. * FUNKTION:     half_down()     (eine halbe bildschirmseite runter)
  192. *
  193. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  194. * BESCHREIBUNG: - es wird versucht, eine halbe bildschirmseite
  195. *               im text nach unten zu springen.
  196. *****************************************************************/
  197.  
  198. int half_down()
  199. {
  200.   return(lines_down(akt_winp->dy / 2));
  201. }
  202.  
  203. /****************************************************************
  204. *
  205. * FUNKTION:     insert()        (zeichen einfuegen)
  206. *
  207. * PARAMETER:    int n: anzahl einzufuegender zeichen
  208. * ERGEBNIS:     int: Anzahl tatsaechlich eingefuegter Zeichen
  209. * BESCHREIBUNG: - fuer n zeichen wird ab der aktuellen position
  210. *               platz geschaffen
  211. *               - die Anzahl der tatsaechlich eingefuegten
  212. *               Zeichen wird zurueckgegeben
  213. *****************************************************************/
  214.  
  215. int insert(n)
  216. register int n;
  217. {
  218.   /* *** interne Daten und Initialisierung *** */
  219.   register int n2 = 0, /* Anzahl wirklich einzufuegender Positionen */
  220.            old_sc = akt_winp->screencol, /* alte Cursorspalte   */
  221.            old_tc; /* alte Cursorspalte intern                  */
  222.  
  223.   fill_buff(); /* sicherstellen, dass aktuelle Zeile im Puffer ist */
  224.   old_tc = akt_winp->textcol; /* Cursorspalte merken */
  225.   eol(); /* Falls hinter Zeilenend nicht genug Platz fuer n Zeichen, */
  226.   if((n2 = MAXLENGTH - akt_winp->screencol) > n) /* dann weniger einfuegen */
  227.     n2 = n;                      /* Im Unterstreich-Modus pro Zeichen 3 */
  228.   n2 *= 1+2*akt_winp->underflag; /* Bytes einfuegen. */
  229.   akt_winp->textcol = old_tc;    /* Cursorspalte merken */
  230.   akt_winp->screencol = old_sc;
  231.   if(n2)                         /* noch platz da ? */
  232.   {
  233.     akt_winp->changeflag = TRUE;  /* Text als geaendert markieren */
  234.     linebuff[3*MAXLENGTH-n2] = '\0'; /* Neues Ende setzen */
  235.     /* Ab Cursor alles um n2 Postionen nach rects */
  236.     revcpy(&linebuff[akt_winp->textcol+n2],&linebuff[akt_winp->textcol]);
  237.     /* Falls die Anzahl einzufuegender Zeichen groesser als die Laenge
  238.       des zu verschiebenden Textes ist, wird '\0' nicht durch revcpy
  239.       ueberschrieben. Dies muss man dann hier nachholen.               */
  240.     if (n2 > 3*MAXLENGTH-n2-akt_winp->textcol)
  241.       linebuff[3*MAXLENGTH-n2] = ' ';     /* Blockgrenzen in screencol-Mass */
  242.     insdel_blockadapt(n2/(1+2*akt_winp->underflag)); /* anpassen */
  243.   }
  244.   return(n2 / (1 + 2*akt_winp->underflag));
  245. }
  246.  
  247. /****************************************************************
  248. *
  249. * FUNKTION:     enter_char()    (zeichen an aktuelle pos kopieren)
  250. *
  251. * PARAMETER:    char c: einzufuegendes zeichen
  252. * ERGEBNIS:     TRUE/FALSE
  253. * BESCHREIBUNG: - das zeichen c wird an die aktuelle position ko-
  254. *               piert
  255. *               - danach wird check_underl() aufgerufen
  256. *               - das neue Zeichen wird angezeigt und evtl. der
  257. *               Bildschirm gescrollt
  258. *****************************************************************/
  259.  
  260. int enter_char(c)
  261. register char c;
  262. {
  263.   /* *** interne Daten und Initialisierung *** */
  264.   register int cu_ret = FALSE; /* Rueckgabewert der check_underl()-Funktion */
  265.  
  266.   fill_buff(); /* sicherstellen, dass aktuelle Zeile im Puffer ist */
  267.   if(akt_winp->screencol < MAXLENGTH) /* Nur wenn Cursor nicht hinter */
  268.   {                                   /* Zeilenende steht             */
  269.     akt_winp->changeflag = TRUE; /* Text als geaendert markieren */
  270.     if(akt_winp->underflag) /* Unterstreichung aktiv ? */
  271.     {                       /* Dann vor dem Zeichen _ und  einsetzen */
  272.       linebuff[akt_winp->textcol] = '_';
  273.       linebuff[akt_winp->textcol+1] = '';
  274.       linebuff[akt_winp->textcol+2] = c;
  275.     }
  276.     else
  277.     {
  278.       linebuff[akt_winp->textcol] = c;
  279.       cu_ret = check_underl(); /* pruefen ob Unterstreichung entstanden ist */
  280.     }
  281.     if (akt_winp->screencol-akt_winp->ws_col >= akt_winp->dx-1)
  282.     { /* Testen, ob horizontal gescrollt werden muss */
  283.       /* Wenn ja, dann normal die voreingestellte Weite. Sollte diese */
  284.       /* groesser als die Fensterbreite sein, dann 1/4 Fensterbreite  */
  285.       akt_winp->ws_col += EC_SCROLL_WIDTH < akt_winp->dx ?
  286.               EC_SCROLL_WIDTH : akt_winp->dx / 4 + 1;
  287.       if(akt_winp->ws_col >= MAXLENGTH) /* Zu weit, dann eins zurueck */
  288.     akt_winp->ws_col = MAXLENGTH-1;
  289.       show_win(W_AKT);  /* Fensterinhalt neu anzeigen */
  290.       fill_buff(); /* aktuelle Zeile wieder in Puffer kopieren */
  291.     }
  292.     else  /* Wenn nicht gescrollt werden musste: */
  293.       if (cu_ret) /*Bei neu entstandener Unterstreichung Zeile neu anzeigen */
  294.     lineout(akt_winp->textline-akt_winp->ws_line);
  295.       else        /* Sonst nur neu eingefuegtes Zeichen */
  296.     fastcharout(akt_winp->textline-akt_winp->ws_line,
  297.             akt_winp->screencol-akt_winp->ws_col,
  298.             linebuff+akt_winp->textcol,akt_winp->insflag?INSERT:PUT);
  299.     akt_winp->textcol+= 1+2*akt_winp->underflag;
  300.     akt_winp->screencol++; /* Cursorspalte anpassen */
  301.     return(TRUE);
  302.   }
  303.   return(FALSE); /* Cursor stand hinter dem Zeilenende */
  304. }
  305.  
  306. /*****************************************************************************
  307. *
  308. *  Funktion      Neue Zeile in Text einkoppeln (koppel_line)
  309. *  --------
  310. *
  311. *  Parameter    : modus     :
  312. *                   Typ          : int
  313. *                   Wertebereich : ADAPT_COORS,IGNORE_COORS
  314. *                   Bedeutung    : ADAPT_COORS:  Block- und Markerpositionen
  315. *                                  sowie letzte Position werden angepasst
  316. *                                  IGNORE_COORS: ... werden nicht angepasst
  317. *
  318. *  Beschreibung : Fuer eine neue Zeile wird Speicherplatz alloziert.
  319. *                 Anschliessend wird das Element korrekt hinter alinep
  320. *                 eingehaengt. Die neu eingefuegte Zeile wird zur
  321. *                 aktuellen Zeile.
  322. *                 Abhaengig vom Modus wird nl_blockadapt aufgerufen
  323. *
  324. *****************************************************************************/
  325.  
  326. void koppel_line(modus)
  327. int modus;
  328. {
  329.   /* *** interne Daten und Initialisierung *** */
  330.   register zeil_typ *zeile = (zeil_typ*) reserve_mem(sizeof(zeil_typ));
  331.        /* zeile zeigt auf neu eingehaengte Zeile */
  332.  
  333.   if(modus == ADAPT_COORS)    /* evtl. Blockkoordinaten anpassen */
  334.     nl_blockadapt();
  335.   zeile->prev = akt_winp->alinep;       /* in Liste einhaengen      */
  336.   zeile->next = akt_winp->alinep->next;
  337.   zeile->next->prev = zeile;
  338.   akt_winp->alinep->next = zeile;
  339.   akt_winp->alinep = zeile;
  340.   akt_winp->alinep->text = NULL;        /* Zeile als leer markieren */
  341.   akt_winp->textcol = akt_winp->screencol = 0; /* Cursor in Spalte 0 */
  342.   akt_winp->maxline++;  /* Zeilenzahl und Cursorzeile haben sich erhoeht */
  343.   akt_winp->textline++;
  344.   akt_winp->changeflag = TRUE; /* Text wurde geaendert */
  345. }
  346.  
  347. /****************************************************************
  348. *
  349. * FUNKTION:     new_line()      (zeile splitten)
  350. *
  351. * ERGEBNIS:       TRUE, FALSE
  352. * BESCHREIBUNG: - die aktuelle zeile wird an der aktuellen po-
  353. *               sition gespalten und der rechte teil in eine
  354. *               neue, der aktuellen zeile nachfolgenden zeile
  355. *               kopiert
  356. *               - diese neue zeile wird dann zur aktuellen zeile,
  357. *               wobei der cursor in die erste spalte gesetzt
  358. *               wird
  359. *               - Wenn durch das Einfuegen der neuen Zeile das
  360. *               Zeilenlimit ueberschritten wuerde, wird keine
  361. *               Zeile eingefuegt und FALSE zurueckgegeben.
  362. *               Sonst ist der RETURN-Wert TRUE.
  363. *
  364. *****************************************************************/
  365.  
  366. int new_line()
  367. {
  368.   /* *** interne Daten und Initialisierung *** */
  369.   register char *zeil_anf, /* Zeiger auf Anfang der neuen Zeile        */
  370.         *ltext;    /* Zeiger auf aktuelle Zeile                */
  371.   int           old_sc = akt_winp->screencol, /* alte Cursorspalte     */
  372.         y;         /* Zeilennummer absolut auf Bildschirm      */
  373.   short int     rc;        /* Zeichen, mit dem Rahmen restauriert wird */
  374.  
  375.   if(akt_winp->maxline < MAX_ANZ_LINES - 1)
  376.   {
  377.     check_buff();                       /* eventuell Puffer in Text zurueck */
  378.     ltext = akt_winp->alinep->text;
  379.     zeil_anf = fastzeichen(akt_winp->screencol);/* Anfang neuer Zeile holen */
  380.     koppel_line(ADAPT_COORS);   /* Eine neue Zeile erzeugen */
  381.     if(zeil_anf != &space)   /* wenn nicht am Zeilenende gesplittet wurde */
  382.     {
  383.       y = akt_winp->textline-akt_winp->ws_line;
  384.       wmove(akt_winp->winp, /* Zur Cursorposition auf Bildschirm */
  385.         y,old_sc-akt_winp->ws_col+1);
  386.       /* Die Cursorposition liegt nun in der Zeile vor der aktuellen Zeile,
  387.      da koppel_line die neue Zeile zur aktuellen macht. */
  388.       wclrtoeol(akt_winp->winp); /* Rest der aktuellen Zeile loeschen */
  389.       if(y == 1)
  390.       rc = REST_ARR_UP | 256*A_STANDOUT;
  391.     else
  392.       if(y == akt_winp->dy)
  393.         rc = REST_ARR_DN | 256*A_STANDOUT;
  394.       else
  395.         rc = REST_CHAR | 256*A_STANDOUT;
  396.       mvwaddch(akt_winp->winp,y,
  397.            akt_winp->dx+1,rc); /* Rechten Rahmen restaurieren */
  398.       akt_winp->alinep->text = save_text(zeil_anf);/* neue zeile abspeichern*/
  399.       *zeil_anf = '\0';  /* ende alte zeile setzen und neue alte Zeile */
  400.       akt_winp->alinep->prev->text = save_text(ltext);  /* abspeichern */
  401.       free(ltext);                              /* alte zeile freigeben   */
  402.     }
  403.     return (TRUE);                              /* Einfuegen hat geklappt */
  404.   }
  405.   return (FALSE);
  406. }
  407.  
  408. /*****************************************************************************
  409. *
  410. *  Funktion       Zeile loeschen (del_line)
  411. *  --------
  412. *
  413. *  Parameter    : modus     :
  414. *                   Typ          : int
  415. *                   Wertebereich : IGNORE_COORS, ADAPT_COORS
  416. *                   Bedeutung    : IGNORE_COORS: del_line wird von Blockfunktion
  417. *                                  aufgerufen
  418. *                                  ADAPT_COORS: del_line wird nicht von einer
  419. *                                  Blockfunktion aufgerufen
  420. *
  421. *  Ergebnis     :
  422. *                   Typ          : int
  423. *                   Wertebereich : NO_LINE_DEL,LAST_LINE_DEL,OTHER_LINE_DEL
  424. *                   Bedeutung    : NO_LINE_DEL : Konnte keine Zeile loeschen
  425. *                                  OTHER_LINE_DEL : Zeile ungleich letzter
  426. *                                                   geloescht
  427. *                                  LAST_LINE_DEL : Letzte Zeile geloescht
  428. *
  429. *  Beschreibung : Die aktuelle Zeile wird aus der Zeilenliste ausgekoppelt
  430. *                 und der dafuer reservierte Speicherplatz freigegeben.
  431. *                 Wird die letzte Zeile des Textes geloescht, dann wird der
  432. *                 Cursor intern um eine Zeile nach oben bewegt und LAST_LINE_DEL
  433. *                 zurueckgegeben.
  434. *                 Wird die Zeile von einer Blockfunktion, z.B. del_normal
  435. *                 aufgerufen, so wird nicht dl_blockadapt aufgerufen, da
  436. *                 schon die Blockfunktion die Anpassung der Marker und der
  437. *                 letzten Position vornimmt.
  438. *
  439. *****************************************************************************/
  440.  
  441. int del_line(modus)
  442. int modus;
  443. {
  444.   /* *** interne Daten *** */
  445.   register zeil_typ *zeile; /* Zeiger auf nachfolgende Zeile */
  446.  
  447.   if (akt_winp->textline != -1)               /* Dummyzeile nicht loeschen */
  448.   {
  449.     akt_winp->changeflag = TRUE;  /* Text als veraendert markieren */
  450.     if(modus == ADAPT_COORS)      /* evtl. Blockgrenzen anpassen */
  451.       dl_blockadapt();
  452.     bufflag = FALSE;                    /* Pufferinhalt ist egal */
  453.     /* Zeile aus Textliste auskoppeln */
  454.     akt_winp->alinep->next->prev = akt_winp->alinep->prev;
  455.     akt_winp->alinep->prev->next = zeile = akt_winp->alinep->next;
  456.     line_free(akt_winp->alinep->text);  /* Zeile freigeben */
  457.     free (akt_winp->alinep);
  458.     akt_winp->alinep = zeile;
  459.     if (akt_winp->textline == akt_winp->maxline--)   /* unterste Textzeile? */
  460.     {
  461.       if(akt_winp->maxline == -1)                 /* allerletzte Textzeile? */
  462.       {
  463.     akt_winp->textline--;                        /* textline auf -1 */
  464.     akt_winp->screencol = 0;
  465.       }
  466.       else
  467.     up();                                         /* eins hoch */
  468.       return (LAST_LINE_DEL);
  469.     }
  470.     return (OTHER_LINE_DEL);
  471.   }
  472.   return (NO_LINE_DEL);
  473. }
  474.  
  475. /*****************************************************************************
  476. *
  477. *  Funktion       Gehe zu Zeile x (gotox)
  478. *  --------
  479. *
  480. *  Parameter    : zeile     :
  481. *                   Typ          : int
  482. *                   Wertebereich : 1-MAX_ANZ_LINES
  483. *                   Bedeutung    : Zeile, die angesprungen werden soll.
  484. *
  485. *  Beschreibung : Es wird getestet, welcher Weg zur uebergebenen Zeile der
  486. *                 kuerzeste ist : vom Start, vom Ende oder von der aktuellen
  487. *                 Zeile aus. Ueber diesen Weg wird dann alinep des aktuellen
  488. *                 Windows gesetzt. textline wird korrekt angepaßt.
  489. *
  490. *****************************************************************************/
  491.  
  492. void gotox (zeile)
  493. register int zeile;
  494. {
  495.   /* *** interne Daten *** */
  496.   register int dist; /* Entfernung zur gewuenschten Zeile */
  497.  
  498.   if(akt_winp->maxline < 0) /* Text leer, dann raus */
  499.     return;
  500.   if(zeile > akt_winp->maxline) /* Zeilennummer zu gross, dann */
  501.     zeile = akt_winp->maxline;  /* zur letzten Zeile           */
  502.   if(zeile < 0)   /* Wenn Zeilennummer kleiner als 0, dann zur ersten */
  503.     zeile = 0;
  504.  
  505.   dist = akt_winp->textline - zeile; /* Entfernung berechnen */
  506.   check_buff(); /* Puffer in Text falls man in aktueller Zeile bleibt */
  507.   /* Pruefen, ob es guenstig ist, von der aktuellen Postion loszulaufen */
  508.   if (abs(dist) <= zeile && abs(dist) <= akt_winp->maxline-zeile)
  509.     if (dist < 0)              /* Abhaengig vom Vorzeichen von dist */
  510.       lines_down (abs(dist));  /* hoch oder runter gehen */
  511.     else
  512.       lines_up   (abs(dist));
  513.   else /* Es bietet sich an, vom Anfang oder vom Ende loszulaufen */
  514.   {
  515.     akt_winp->alinep = akt_winp->dummyp;
  516.     if (zeile < akt_winp->maxline-zeile) /* besser vom Anfang ? */
  517.     {
  518.       akt_winp->textline = -1;           /* dann vorwaerts */
  519.       lines_down (zeile+1);
  520.     }
  521.     else                                 /* sonst rueckwaerts */
  522.     {
  523.       akt_winp->textline = akt_winp->maxline+1;
  524.       lines_up (akt_winp->maxline-zeile+1);
  525.     }
  526.   }
  527. }
  528.  
  529. /*****************************************************************************
  530. *
  531. *  Funktion       aktuelle  Zeile einruecken (indent_line)
  532. *  --------
  533. *
  534. *  Beschreibung : Die aktuelle Zeile wird so eingerueckt, dass die Zeile
  535. *                 am Anfang soviele Blanks enthaelt wie die darueberliegende.
  536. *
  537. *****************************************************************************/
  538.  
  539. void indent_line()
  540. {
  541.   /* *** interne Daten und Initialisierung *** */
  542.   register int i,     /* Loopvariable fuer Marker und Blanks */
  543.            anz=0; /* Zaehler fuer Einrueckungsweite */
  544.   int          sc=akt_winp->screencol; /* Zwischenspeicher fuer Cursorspalte */
  545.   char         *txt,  /* Zeiger auf vorangehende Zeile  */
  546.            *txt2; /* Zeiger in neuen Zeilenstring   */
  547.  
  548.   check_buff(); /* sicherstellen, dass Pufferinhalt im Text ist */
  549.   if (txt = akt_winp->alinep->prev->text)
  550.   { /* Wenn vorhergehende Zeile nicht leer, dann fuehrende Blanks zaehlen */
  551.     while(*txt == ' ' && fastright(&txt,1))
  552.       anz++;    /* Zaehlen, wie weit eingerueckt wird */
  553.  
  554.     swap_int(&akt_winp->screencol,&sc); /* Alte Cursorspalte zur neuen machen */
  555.     insdel_blockadapt(anz); /* Block, lastpos und Marker anpassen */
  556.     swap_int(&akt_winp->screencol,&sc); /* Cursor wieder an neuen Zeilenstart */
  557.  
  558.     if(akt_winp->alinep->text) /* Wenn einzurueckende Zeile nicht leer: */
  559.     { /* Platz fer Zeile und einzufuegende Blanks allozieren */
  560.       txt2 = txt = reserve_mem(strlen(akt_winp->alinep->text)
  561.               + akt_winp->screencol+1);
  562.       for(i=0;i<akt_winp->screencol;i++)   /* Blanks eintragen */
  563.     *txt2++ = ' ';
  564.       strcpy(txt2,akt_winp->alinep->text); /* Alte Zeile dranhaengen */
  565.       free(akt_winp->alinep->text);   /* Alte Zeile freigeben */
  566.       akt_winp->alinep->text = txt;
  567.     }
  568.   }
  569. }
  570.  
  571. /*****************************************************************************
  572. *
  573. *  Funktion       in Zeile Anzahl Zeichen nach links (fastleft)
  574. *  --------
  575. *
  576. *  Parameter    : zeile     :
  577. *                   Typ          : char**
  578. *                   Wertebereich : Doppelpointer auf ASCII-Zeichenkette
  579. *                   Bedeutung    : Character, ab dem nach links bewegt werden
  580. *                                  soll. Muss auf einen Character in
  581. *                                  akt_winp->alinep->text zeigen.
  582. *
  583. *  Parameter    : anzahl    :
  584. *                   Typ          : int
  585. *                   Wertebereich : 0-MAXLENGTH
  586. *                   Bedeutung    : Anzahl der Positionen, um die nach links
  587. *                                  gegangen werden soll.
  588. *
  589. *  Ergebnis     :
  590. *                   Typ          : int
  591. *                   Wertebereich : TRUE, FALSE
  592. *                   Bedeutung    : TRUE : konnte anzahl Zeichen nach links
  593. *                                  FALSE: konnte nicht anzahl Zeichen nach
  594. *                                         links
  595. *
  596. *  Beschreibung : Der pointer auf den String (*zeile) wird unter Berueck-
  597. *                 sichtigung von unterstrichenen Zeichen so oft nach links
  598. *                 bewegt, bis die vorgegebene Anzahl erreicht ist oder
  599. *                 man am linken Zeilenrand angekommen ist.
  600. *                 akt_winp->screencol wird angepasst.
  601. *
  602. *****************************************************************************/
  603.  
  604. int fastleft(zeile,anzahl)
  605. register char **zeile;
  606. register int  anzahl;
  607. {
  608.   while (anzahl--)
  609.   {
  610.     if (*zeile > akt_winp->alinep->text)  /* Zeilenanfang ? */
  611.     {
  612.       if (*zeile-2 >= akt_winp->alinep->text    /* Steht man auf einem      */
  613.       && *(*zeile-1)=='' && *(*zeile-2)=='_') /* unterstrichenem Zeichen? */
  614.     *zeile -= 3;   /* Dann 3 nach links, */
  615.       else
  616.     (*zeile)--;    /* sonst nur 1 nach links */
  617.       akt_winp->screencol--;  /* screencol anpassen */
  618.     }
  619.     else
  620.       return (FALSE);   /* Zeilenanfang, also FALSE zurueckgeben */
  621.   }
  622.   return (TRUE); /* Konnte anzahl Zeichen nach rechts, also TRUE zurueck */
  623. }
  624.  
  625. /*****************************************************************************
  626. *
  627. *  Funktion       in Zeile Anzahl Zeichen nach rechts (fastright)
  628. *  --------
  629. *
  630. *  Parameter    : zeile     :
  631. *                   Typ          : char**
  632. *                   Wertebereich : Doppelpointer auf ASCII-Zeichenkette
  633. *                   Bedeutung    : Character, ab dem nach rechts bewegt werden
  634. *                                  soll. Muss auf einen Character in
  635. *                                  akt_winp->alinep->text zeigen.
  636. *
  637. *  Parameter    : anzahl    :
  638. *                   Typ          : int
  639. *                   Wertebereich : 0-MAXLENGTH
  640. *                   Bedeutung    : Anzahl der Positionen, um die nach rechts
  641. *                                  gegangen werden soll.
  642. *
  643. *  Ergebnis     :
  644. *                   Typ          : int
  645. *                   Wertebereich : TRUE, FALSE
  646. *                   Bedeutung    : TRUE : konnte anzahl Zeichen nach rechts
  647. *                                  FALSE: konnte nicht anzahl Zeichen nach
  648. *                                         rechts
  649. *
  650. *  Beschreibung : Der pointer auf den String (*zeile) wird unter Berueck-
  651. *                 sichtigung von unterstrichenen Zeichen so oft nach rechts
  652. *                 bewegt, bis die vorgegebene Anzahl erreicht ist oder
  653. *                 man am rechten Zeilenrand angekommen ist.
  654. *                 akt_winp->screencol wird angepasst.
  655. *
  656. *****************************************************************************/
  657.  
  658. int fastright(zeile,anzahl)
  659. register char **zeile;
  660. register int  anzahl;
  661. {
  662.   while (anzahl--)
  663.   {
  664.     if (*(*zeile+1))  /* Zeilenende ? */
  665.     {
  666.       akt_winp->screencol++; /* screencol anpassen */
  667.       (*zeile)++; /* rechts davon _^H, dann noch 2 Positionen weiter */
  668.       if (**zeile=='_' && *(*zeile+1)=='' && *(*zeile+2))
  669.     *zeile += 2;
  670.     }
  671.     else
  672.       return (FALSE);   /* Zeilenende, also FALSE zurueckgeben */
  673.   }
  674.   return (TRUE); /* Konnte anzahl Zeichen nach rechts, also TRUE zurueck */
  675. }
  676.  
  677. /*****************************************************************************
  678. *
  679. *  Funktion       Zeilenlaenge der aktuellen Zeile berechnen (fastll)
  680. *  --------
  681. *
  682. *  Parameter    : txt       :
  683. *                   Typ          : char*
  684. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  685. *                   Bedeutung    : String, vom dem Laenge in screencol-Mass
  686. *                                  berechnet werden soll.
  687. *
  688. *  Ergebnis     :
  689. *                   Typ          : int
  690. *                   Wertebereich : 0-MAXLENGTH
  691. *                   Bedeutung    : Laenge der aktuellen Zeile in screencol-Mass
  692. *
  693. *  Beschreibung : Die aktuelle Zeile (akt_winp->alinep->text) wird bis zum
  694. *                 Ende durchgegangen, wobei berechnet wird, welche screencol-
  695. *                 position das Zeilenende hat.
  696. *
  697. *****************************************************************************/
  698.  
  699. int fastll(txt)
  700. register char *txt;
  701. {
  702.   /* *** interne Daten und Initialisierung *** */
  703.   register int sc = 0; /* vorlaeufiger return-Wert */
  704.  
  705.   if (!txt)      /* Zeile leer ? */
  706.     return (0);
  707.   while (*txt)  /* Zeilenende ? */
  708.   {
  709.     sc++;
  710.     if (*txt++ == '_' && *txt=='' && txt[1])
  711.       txt += 2; /* bei unterstrichenem Zeichen insgesamt 3 nach rechts */
  712.   }
  713.   return (sc);   /* Zeilenlaenge in screencol-Mass zurueckgeben */
  714. }
  715.  
  716. /*****************************************************************************
  717. *
  718. *  Funktion       hole zeichen aus aktueller zeile (fastzeichen)
  719. *  --------
  720. *
  721. *  Parameter    : n         :
  722. *                   Typ          : int
  723. *                   Wertebereich : 0 - MAXLENGTH-1
  724. *                   Bedeutung    : index des zu ermittelnden Zeichens
  725. *
  726. *  Ergebnis     :
  727. *                   Typ          : char*
  728. *                   Wertebereich : Pointer auf ASCII-Zeichen
  729. *                   Bedeutung    : Zeichen an Position n (s.u.)
  730. *
  731. *  Beschreibung : Die aktuelle Zeile wird bis zur Position n durchlaufen,
  732. *                 wobei _^Hx als ein Zeichen gewertet wird. Daher ist der
  733. *                 Rueckgabewert auch ein Pointer, da ein unterstrichenes
  734. *                 Zeichen mit dem _ beginnt und aus drei Codes besteht.
  735. *                 Ist die Zeile leer oder wird versucht, vor oder hinter der
  736. *                 Zeile zuzugreifen, wird die Addresse der Variablen
  737. *                 space zurueckgeliefert, die ein Leerzeichen enthaelt.
  738. *
  739. *****************************************************************************/
  740.  
  741. char *fastzeichen(n)
  742. register int n;
  743. {
  744.   /* *** interne Daten *** */
  745.   register int  sc;     /* Zaehler fuer Durchlaufen der Zeile */
  746.   register char *zeile; /* Zeiger auf aktuellen Zeilentext    */
  747.  
  748.   check_buff(); /* sicherstellen, dass Pufferinhalt im Text ist */
  749.  
  750.   /* Wenn Zeile leer ist oder n hinters Zeilenende oder vor den       */
  751.   /* Zeilenanfang zeigt, dann die Adresse des globalsn Blanks zurueck */
  752.   if (!(zeile = akt_winp->alinep->text) || (n > MAXLENGTH) || (n < 0))
  753.     return(&space);
  754.  
  755.   for(sc=0;(sc<n) && *zeile;sc++)  /* Zeile durchlaufen */
  756.     if(*zeile++ == '_' && *zeile == '' && zeile[1])
  757.       zeile+=2;
  758.  
  759.   if(!*zeile)        /* Zeilenende erreicht, dann Adresse des */
  760.     return(&space);  /* globalen Blanks zurueckgeben          */
  761.  
  762.   return(zeile);     /* Sonst das Zeichen, auf dem man steht  */
  763. }
  764.  
  765. /*****************************************************************************
  766. *
  767. *  Funktion       Zeile in Datei schreiben (put_zeile)
  768. *  --------
  769. *
  770. *  Parameter    : line      :
  771. *                   Typ          : char *
  772. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  773. *                   Bedeutung    : zu schreibende Zeile
  774. *
  775. *                 f         :
  776. *                   Typ          : FILE *
  777. *                   Wertebereich : Dateipointer
  778. *                   Bedeutung    : Datei, in die Zeile geschrieben werden soll
  779. *
  780. *  Beschreibung : Die Zeile wird in die Datei geschrieben. Abhaengig von
  781. *                 akt_winp->tabflag werden Spaces am Anfang - wenn moeglich -
  782. *                 zu Tabs komprimiert.
  783. *
  784. *****************************************************************************/
  785.  
  786. void put_zeile(line,f)
  787. register char *line;
  788. FILE *f;
  789. {
  790.   /* *** interne Daten und Initialisierung *** */
  791.   register int i,            /* Schleifenzaehler fuer Tabschreiben */
  792.            anz_spaces=0; /* Zaehler fuer fuehrende Blanks      */
  793.  
  794.   if(akt_winp->tabflag) /* Wenn Spaces zu Tabs komprimiert werden sollen: */
  795.   {
  796.     while(*line++ == ' ') /* Spaces am Zeilenanfang zaehlen */
  797.       anz_spaces++;
  798.     for(i=anz_spaces/STD_TAB;i>0;i--)  /* Tabs in Datei schreiben */
  799.       fputc('\t',f);
  800.     line -= anz_spaces%STD_TAB + 1;  /* Nichtkomprimierte Spaces schreiben */
  801.   }
  802.   fputs(line,f); /* Rest der Zeile in Datei schreiben */
  803. }
  804.  
  805. /*****************************************************************************
  806. *
  807. *  Funktion       Schreib File auf Platte (schreib_file)
  808. *  --------
  809. *
  810. *  Ergebnis     :   Typ          : int
  811. *                   Wertebereich : TRUE,FALSE
  812. *                   Bedeutung    : Flag, ob Operation erfolgreich
  813. *
  814. *  Beschreibung : Der im aktuellen Fenster stehende Text wird in die
  815. *                 Datei geschrieben, deren Name in der Window-Struktur
  816. *                 angegeben ist. NULL-Pointer werden in Leerzeilen kon-
  817. *                 vertiert.
  818. *
  819. *****************************************************************************/
  820.  
  821. int schreib_file ()
  822. {
  823.   /* *** interne Daten *** */
  824.   FILE     *f;  /* Pointer fuer Schreibdatei                        */
  825.   zeil_typ *tp; /* Zeiger auf aktuelle Zeile                        */
  826.   int      len; /* Laenge des Filenamens vor Anhaengen von .bak     */
  827.   char     *fn, /* Zeiger auf Dateinamen ohne Pfad                  */
  828.        *sc, /* Zur Suche des Punktes im Filenamen               */
  829.        buff[MAXLENGTH+1]; /* fuer Fehlermeldungen und Filenamen */
  830.  
  831.   if (akt_winp->read_only)
  832.   {
  833.     sprintf(buff,PROMPT_WRTPROT,akt_winp->filename);
  834.     pe_or(buff);
  835.     return (FALSE);
  836.   }
  837.   check_buff(); /* Pufferinhalt evtl. in Text uebernehmen */
  838.   sprintf(buff,PROMPT_SAVING,akt_winp->filename);
  839.   print_stat(buff);
  840.   if(backupflag && !access(akt_winp->filename,2))   /* write permission? */
  841.   {                   /* .bak erzeugen */
  842.     strcpy(buff,akt_winp->filename);
  843. #ifdef OS2  /* OS/2 verkraftet auch xxx.c.bak !!! */
  844.     strcat(buff,".bak");
  845. #else
  846.     if(sc = strchr(fn=sname(buff),'.')) /* Punkt im Filenamen suchen */
  847.       len = sc-fn;      /* Falls gefunden, ist Länge die Länge bis zum Punkt */
  848.     else                /* Sonst ist es die gesamte Länge des Filenamens */
  849.       len = strlen(fn); /* Kann nicht länger als 8 Zeichen sein. */
  850.     strcpy(&fn[len],".bak");  /* Filename des .bak-Files erzeugen */
  851. #endif
  852.     unlink(buff);     /* falls schon ein .bak gleichen Namens existiert */
  853.     rename(akt_winp->filename,buff);   /* Datei in ...bak umbenennen */
  854.   }
  855.   if (f = fopen (akt_winp->filename,"w"))
  856.   {
  857.     for (tp = akt_winp->dummyp->next; tp != akt_winp->dummyp; tp = tp->next)
  858.     { /* Alle Zeilen durchgehen und in die Datei schreiben */
  859.       if (tp->text)
  860.     put_zeile(tp->text,f);
  861.       putc('\n',f);
  862.     }
  863.   }
  864.   else  /* Fehler beim Oeffnen der Datei */
  865.   {
  866.     clear_stat();
  867.     print_stat(PROMPT_ERRWRITE);
  868.     pe_or(akt_winp->filename);
  869.     return(FALSE);
  870.   }
  871.   akt_winp->changeflag = FALSE;               /* changeflag zuruecksetzen */
  872.   fclose(f);
  873.   chmod(akt_winp->filename,akt_winp->attribs); /* Modus korrekt setzen */
  874.   clear_stat();
  875.   return(TRUE);
  876. }
  877.  
  878.  
  879. /*****************************************************************************
  880. *
  881. *  Funktion       Tab in Puffer einfuegen (tab_in_buff)
  882. *  --------
  883. *
  884. *  Parameter    : buff      :
  885. *                   Typ          : char *
  886. *                   Wertebereich : Pointer auf char-Puffer
  887. *                   Bedeutung    : Puffer, in den Tab eingefuegt werden soll
  888. *
  889. *                 sc        :
  890. *                   Typ          : int *
  891. *                   Wertebereich : Pointer auf Integer
  892. *                   Bedeutung    : aktuelle Bildschirmposition im Puffer
  893. *
  894. *                 count     :
  895. *                   Typ          : int *
  896. *                   Wertebereich : Pointer auf Integer
  897. *                   Bedeutung    : aktuelle Position im Puffer
  898. *
  899. *  Beschreibung : Bis zur naechsten Tab-Position werden im Puffer Spaces einge-
  900. *                 fuegt.
  901. *
  902. *****************************************************************************/
  903.  
  904. void tab_in_buff(buff,sc,count)
  905. register char *buff;
  906. register int *sc,*count;
  907. {
  908.   do
  909.   {
  910.     buff[(*count)++] = ' ';
  911.   } while(++*sc % STD_TAB && *sc < MAXLENGTH);
  912. }
  913.  
  914. /*****************************************************************************
  915. *
  916. *  Funktion       Datei einlesen (lies_file)
  917. *  --------
  918. *
  919. *  Beschreibung : In die Fensterstruktur des aktuellen Fensters wird der
  920. *                 Text aus der Datei, deren Name in filename steht, geladen.
  921. *                 Evtl. vorkommende Tabs werden expandiert.
  922. *
  923. *****************************************************************************/
  924.  
  925. int lies_file()
  926. {
  927.   /* *** interne Daten *** */
  928.   FILE        *f;     /* Zeiger fuer Ausgabedatei                       */
  929.   char        buff[3*MAXLENGTH+2],   /* Eingabepuffer                   */
  930.           buff2[3*MAXLENGTH+2],  /* Ausgabepuffer                   */
  931.           nlflag; /* Flag zeigt an ob komplette Zeile gelesen wurde */
  932.   int         len,    /* Laenge der eingelesenen Zeile                  */
  933.           in,     /* Index in Eingabepuffer                         */
  934.           out,    /* Index in Ausgabepuffer                         */
  935.           sc;     /* Zeilenlaenge in screencol-Mass                 */
  936.   struct stat f_info; /* Zum Einlesen der Dateiattribute                */
  937.  
  938.   /* Dummyelement fuer Textstruktur allozieren */
  939.   akt_winp->dummyp = (zeil_typ*) reserve_mem (sizeof (zeil_typ));
  940.   akt_winp->dummyp->prev = akt_winp->dummyp->next = akt_winp->alinep = akt_winp->dummyp;
  941.   akt_winp->dummyp->text = NULL;
  942.  
  943.   /* Cursorposition und andere Variablen initialisieren */
  944.   akt_winp->textline = akt_winp->maxline = -1;
  945.   akt_winp->screencol = akt_winp->textcol = 0;
  946.   akt_winp->attribs = STD_FATTR;
  947.   akt_winp->read_only = FALSE;
  948.   akt_winp->changeflag = FALSE;
  949.  
  950.   if (!(f = fopen (akt_winp->filename,"r")))
  951.   {
  952.     sprintf(buff,PROMPT_ASKNEW,akt_winp->filename);
  953.     return (ja_nein(buff));
  954.   }
  955.   sprintf(buff,PROMPT_LOADING,akt_winp->filename);
  956.   print_stat(buff);
  957.   if (access(akt_winp->filename,2))  /* Testen, ob Datei schreibgeschuetzt */
  958.     akt_winp->read_only = TRUE;      /* und evtl. vermerken */
  959.   if (!stat(akt_winp->filename,&f_info)) /* Fileattribute bestimmen */
  960.     akt_winp->attribs = f_info.st_mode & (S_IWRITE | S_IREAD);
  961.  
  962.   out = sc = 0;
  963.   while (fgets(buff,3*MAXLENGTH + 1,f) && akt_winp->maxline < MAX_ANZ_LINES-1)
  964.   { /* Zeile einlesen, testen ob das ging und ob maximale */
  965.     /* Zeilenanzahl erreicht ist */
  966.     if(buff[(len = strlen(buff))-1] == '\n')
  967.     { /* testen, ob eine komplette Zeile eingelesen wurde */
  968.       nlflag = TRUE;  /* Wenn ja, nlflag setzen */
  969.       buff[--len] = '\0'; /* und '\n' streichen */
  970.     }
  971.     else /* Wenn keine komplette Zeile eingelesen werden konnte */
  972.       nlflag = FALSE;
  973.     in = 0;
  974.     while(in < len)
  975.     {
  976.       if (buff[in] == '_' && buff[in+1] == '' && buff[in+2])
  977.       { /* Wurde ein unterstrichenes Zeichen gelesen, dann den Unter-  */
  978.     buff2[out++] = buff[in++];  /* strich und das Backspace ueber- */
  979.     buff2[out++] = buff[in++];  /* nehmen */
  980.       }
  981.       if(buff[in] == '\t')   /* Tab ? */
  982.     tab_in_buff(buff2,&sc,&out);
  983.       else   /* kein Tab, dann Zeichen in Puffer uebernehmen */
  984.       {
  985.     buff2[out++] = buff[in];
  986.     sc++;  /* Screencol-Laenge der Zeile erhoehen */
  987.       }
  988.       in++;    /* Naechstes Zeichen aus Eingabepuffer */
  989.       if(sc == MAXLENGTH)       /* Aufbereitete Zeile voll ? */
  990.       {
  991.     buff2[out] = '\0'; /* Dann Puffer abschliessen */
  992.     sc = out = 0;      /* Zeile eintragen und neue Zeile anfangen */
  993.     koppel_line(IGNORE_COORS); /* Marker und lastpos sind eh korrupt */
  994.     akt_winp->changeflag = FALSE; /* Falls reserve_mem hängt, soll */
  995.                       /* Text nicht abgespeichert werden */
  996.     akt_winp->alinep->text = save_text (buff2);
  997.       }
  998.     }
  999.     if(nlflag && !(!sc && len)) /* volle Zeilen nicht doppelt eintragen */
  1000.     {
  1001.       buff2[out] = '\0';  /* Puffer abschliessen, eintragen und neue */
  1002.       sc = out = 0;       /* Zeile anfangen */
  1003.       koppel_line(IGNORE_COORS);
  1004.       akt_winp->changeflag = FALSE; /* Kommentar s.o. */
  1005.       akt_winp->alinep->text = save_text(buff2);
  1006.     }               /* buff wird durch fgets besetzt. Schlaegt fgets fehl, */
  1007.     buff[0] = '\0'; /* ist buff[0]=='\0', sonst nicht. Bricht Schleife     */
  1008.   }            /* nicht wegen fgets ab, dann war das Zeilenlimit erreicht. */
  1009.  
  1010.   /* Wurde die letzte Zeile nicht mit \n abgeschlossen, dann wurde die     */
  1011.   /* Zeile noch nicht in den Text eingetragen sondern steht noch in buff2. */
  1012.   if(out)
  1013.   {
  1014.     buff2[out] = '\0'; /* Puffer abschliessen und eintragen */
  1015.     koppel_line(IGNORE_COORS);
  1016.     akt_winp->changeflag = FALSE; /* Kommentar s.o. */
  1017.     akt_winp->alinep->text= save_text(buff2);
  1018.   }
  1019.  
  1020.   clear_stat();
  1021.   if (buff[0] && akt_winp->maxline >= MAX_ANZ_LINES - 1)
  1022.     print_err(PROMPT_FILETOLNG);
  1023.   fclose(f);
  1024.   akt_winp->alinep = akt_winp->dummyp->next; /* Erste Zeile zur aktuellen */
  1025.   akt_winp->textline = akt_winp->maxline != -1 ? 0 : -1;    /* machen */
  1026.   return (TRUE); /* Kein Fehler, Fenster kann geoeffnet werden */
  1027. }
  1028.  
  1029. /*****************************************************************************
  1030. *
  1031. *  Funktion       Text freigeben (free_text)
  1032. *  --------
  1033. *
  1034. *  Beschreibung : Der zum aktuellen Fenster gehoerige Text, inklusive
  1035. *                 akt_winp->dummyp, wird freigegeben.
  1036. *
  1037. *****************************************************************************/
  1038.  
  1039. void free_text()
  1040. {
  1041.   /* *** interne Daten *** */
  1042.   register zeil_typ *n; /* Zeiger auf naechste freizugebende Zeile */
  1043.  
  1044.   akt_winp->alinep = akt_winp->dummyp;
  1045.   do
  1046.   {
  1047.     line_free(akt_winp->alinep->text); /* Text freigeben */
  1048.     n = akt_winp->alinep->next;        /* Zeiger auf naechste Zeile merken */
  1049.     free(akt_winp->alinep);            /* Zeilenstruktur freigeben */
  1050.   }while((akt_winp->alinep = n) != akt_winp->dummyp);
  1051. }
  1052.  
  1053. /*****************************************************************************
  1054. *
  1055. *  Funktion       aktuelle Zeile abspeichern (save_delline)
  1056. *  --------
  1057. *
  1058. *  Beschreibung :  Der text-Pointer der alten Zeile wird in sd_line ge-
  1059. *                  speichert und anschliessend auf NULL gesetzt. Diese
  1060. *                  Funktion wird in do_delline() vor del_line aufgerufen.
  1061. *                  Der Speicherbereich, auf den sd_line zeigt, wird vorher
  1062. *                  mittels line_free() freigegeben.
  1063. *
  1064. *****************************************************************************/
  1065.  
  1066. void save_delline()
  1067. {
  1068.   line_free(sd_line); /* Alte gespeicherte geloeschte Zeile verwerfen */
  1069.   check_buff();  /* evtl. Pufferinhalt in den Text uebernehmen */
  1070.   sd_line = akt_winp->alinep->text; /* text sichern */
  1071.   akt_winp->alinep->text = NULL; /* funktioniert, da Zeile sowieso */
  1072. }                                /* geloescht wird */
  1073.  
  1074. /*****************************************************************************
  1075. *
  1076. *  Funktion       Gespeicherte Zeile wiederherstellen (rest_delline)
  1077. *  --------
  1078. *
  1079. *  Beschreibung : Die mit save_delline gespeicherte Zeile wird in den Text
  1080. *                 vor der aktuellen Zeile eingefuegt. Die neue Zeile wird
  1081. *                 zur aktuellen.  Es wird eine Kopie der gespeicherten Zeile
  1082. *                 angelegt, so dass die Zeile ggf. mehrmals eingefuegt werden
  1083. *                 kann.
  1084. *
  1085. *****************************************************************************/
  1086.  
  1087. void rest_delline()
  1088. {
  1089.   int old_sc = akt_winp->screencol; /* Zwischenspeicher Screencol */
  1090.  
  1091.   if(akt_winp->maxline < MAX_ANZ_LINES-1)
  1092.   { /* Noch Platz fuer Wiederherstellung der geloeschten Zeile ? */
  1093.     check_buff();  /* Pufferinhalt evtl. in Text uebernehmen */
  1094.     if(akt_winp->alinep != akt_winp->dummyp)
  1095.     { /* Wenn Datei Zeilen enthaelt, dann eine Zeile hoch */
  1096.       akt_winp->textline--; /* nummer bleibt gleich, da neue z. = alte z. */
  1097.       akt_winp->alinep = akt_winp->alinep->prev;
  1098.     }
  1099.     koppel_line(ADAPT_COORS); /* Neue Zeile einfuegen, Block anpassen */
  1100.     akt_winp->alinep->text = save_text(sd_line); /* mehrmals einfuegen */
  1101.     akt_winp->screencol = old_sc; /* Screencol restaurieren */
  1102.   } /* nur moeglich, wenn sichergestellt ist, dass sd_line gleichbleibt */
  1103. }
  1104.